package ntd.util;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Opt;
import cn.hutool.core.thread.lock.LockUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.ReUtil;
import ntd.util.fun.ComFun;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.concurrent.locks.StampedLock;

public class ToolCache {

    private static final Map<String, Object> CACHE = new HashMap<>();
    private static final Map<String, Date> EXPIRE_TIME = new HashMap<>();
    // 最大缓存时长 - 8小时
    private static final long MAX_TIME = 1000 * 60 * 60 * 8;

    public static <T> T get(String key) {
        // 如果存在过期时间，则进行过期清理
        if (EXPIRE_TIME.containsKey(key) && DateUtil.compare(DateUtil.date(), EXPIRE_TIME.get(key)) > 0) {
            CACHE.remove(key);
        }
        return (T) CACHE.get(key);
    }

    public static <T> Map<String, T> map(String key) {
        Set<String> keys = CACHE.keySet();
        Map<String, T> map = new HashMap<>();
        for (String item : keys) {
            if (ReUtil.isMatch(key, item)) {
                T t = get(item);
                Opt.ofNullable(t).ifPresent(o -> {
                    map.put(item, o);
                });
            }
        }
        return map;
    }

    public static void set(String key, Object val) {
        set(key, val, MAX_TIME);
    }

    /**
     * 存入缓存
     * @param key
     * @param val
     * @param time 毫秒缓存
     */
    public static void set(String key, Object val, long time) {
        CACHE.put(key, val);
        if (time < 0 || time > MAX_TIME) {
            time = MAX_TIME;
        }
        EXPIRE_TIME.put(key, DateUtil.offsetMillisecond(DateUtil.date(), Math.toIntExact(time)));
    }

    /**
     * 删除缓存内容
     * @param key
     */
    public static void remove(String key) {
        CACHE.remove(key);
        EXPIRE_TIME.remove(key);
    }

    /**
     * 时间锁定
     * @param key 锁定标记
     * @param time 锁定时间
     * @return 锁定结果
     */
    public static boolean lock(String key, long time) {
        key = "lock:" + key;
        Object o = get(key);
        if (ObjectUtil.isNull(o)) {
            set(key, "ok", time);
            return true;
        }
        return false;
    }

    public static void main(String[] args) {
        ReentrantReadWriteLock readWriteLock = LockUtil.createReadWriteLock(false);

        StampedLock stampLock = LockUtil.createStampLock();

        long l = stampLock.readLock();


    }
}
